package co.edu.unal.geditor.model;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.io.Serializable;

import co.edu.unal.geditor.controller.App;
import co.edu.unal.geditor.view.ElementView;

// make all graphic elements Serializable so we can store 
// them to disk (serialization: object to byte stream) and 
// recover them from disk (deserialization: byte stream to object)
public abstract class GraphElement implements Serializable {
	private static final long serialVersionUID = 1L;

	// call next constructor
	protected GraphElement(Point pUL, Point pBD) {
		this(pUL, pBD, Color.BLACK);
	}

	protected boolean normalizeBoundBox() {
		// all but LineElement should normalize the bounding box
		return true;
	}

	// method overloading example: same name, different arguments
	protected GraphElement(Point pUL, Point pBD, Color color) {
		assert pUL != null;
		assert pBD != null;
		assert pUL != pBD;

		m_boundBox = new BoundBox(pUL, pBD);

		setLinesColor(color);

		// default behavior
		setVisible(true);
		m_boundBox.setSelected(false);
		setView();

		if (normalizeBoundBox()) {
			m_boundBox.normalize();
		} else {
			if (!isPolyLine()){
				m_boundBox.setAsLine(true);
			}
		}
		assert m_view != null;
	}

	public void setView() {
		m_view = createView();
	}

	// all graphic elements are responsible
	// for creating its own view
	protected abstract ElementView createView();

	// encapsulate here common behavior
	// to all graphic elements

	// all graphic elements are responsible
	// for knowing how to render themselves:
	public void paint(Graphics g) {
		// delegate responsibility in the view:
		// template method design pattern
		m_view.paint(g);
	}

	public Color getLinesColor() {
		return m_linesColor;
	}

	public void setLinesColor(Color color) {
		assert color != null;

		m_linesColor = color;
	}
	
	public boolean isPolyLine(){
		return false;
	}

	public boolean isVisible() {
		return m_bVisible;
	}

	public void setVisible(boolean visible) {
		m_bVisible = visible;
	}

	public BoundBox getBoundBox() {
		return m_boundBox;
	}

	public Point getUpLeft() {
		return m_boundBox.getLeftUp();
	}

	public Point getDownRight() {
		return m_boundBox.getRightDown();
	}

	public boolean select(BoundBox bb) {
		return m_boundBox.containedin(bb);
	}

	public boolean contain(Point ptContain) {
		boolean retorno = false;
		if (m_boundBox.contain(ptContain)) {
			App.getInstance().getCanvas().setActiveFeedbackGraphElement(this);
			retorno = true;
		}

		return retorno;
	}
	public void moved(int x, int y){
		m_boundBox.getView().moved(x, y);
	}

	public void resizing (Point pt){
		m_boundBox.getView().resizing(pt);
	}
	public Color getFillColor() {
		return m_fillColor;
	}

	public void setFillColor(Color color) {
		m_fillColor = color;
	}
	

	public static Color getDefaultLinesColor() {
		return defaultLinesColor;
	}

	public static void setDefaultLinesColor(Color defaultLinesColor) {
		GraphElement.defaultLinesColor = defaultLinesColor;
	}
	public void setFont(Font m_font) {
		this.m_font = m_font;
	}

	// encapsulate here those attributes
	// common to all graphic elements

	// element's view transient:
	// tell the VM no to store the view
	// when the object is serialized (stored to disk)
	protected transient ElementView m_view=null;
	protected Color m_fillColor;
	// bounding box
	protected BoundBox m_boundBox;
	protected static Color defaultLinesColor = Color.BLACK;

	// line or text color
	protected Color m_linesColor;

	// element status
	protected boolean m_bVisible;
	protected boolean m_bSelected;
	protected Font m_font;
}
